﻿namespace Core.Base
{
    using Contracts.Enums;
    using Contracts.Interfaces;
    using System;
    using System.Globalization;
    
    
    public abstract class FeatureBase<T> : PropertyChangedBase, IFeature<T>, IEquatable<IFeature<T>> 
    {
        private readonly T _value;
        private T _modifiedValue;
        
        /// <summary>
        /// Create a new instance
        /// </summary>
        protected FeatureBase(){}
        /// <summary>
        /// Create a new instance
        /// </summary>
        /// <param name="value">The feature base value</param>
        protected FeatureBase(T value){ _value = value; }
        /// <summary>
        /// Obtains the feature group
        /// </summary>
        public abstract FeatureGroupsEnum FeatureGroup { get; }
        /// <summary>
        /// Obtains the feature type
        /// </summary>
        public abstract FeaturesEnum FeatureType { get; }
        /// <summary>
        /// Obtains the feature name
        /// </summary>
        public virtual string Name { get { return Enum.GetName(typeof (FeaturesEnum), FeatureType); } }
        /// <summary>
        /// Obtains the feature value unit
        /// </summary>
        public abstract string Unit { get; }
        /// <summary>
        /// Determines if the feature value is rounded
        /// </summary>
        public virtual bool IsRounded { get { return false; } }
        /// <summary>
        /// Obtains or defines the feature base value
        /// </summary>
        public virtual T Value
        {
            get { return _value; }
            //set { _value = value; NotifyPropertyChange(() => Value); }
        }
        /// <summary>
        /// Obtains or defines the modified feature value
        /// </summary>
        public virtual T ModifiedValue
        {
            get { return _modifiedValue; }
            set { _modifiedValue = value; NotifyPropertyChange(()=>ModifiedValue); }
        }
        /// <summary>
        /// Determines if the feature value has been modified
        /// </summary>
        public bool IsModified
        {
            get { return !ReferenceEquals(ModifiedValue,null) && !Equals(ModifiedValue,Value); }
        }
        /// <summary>
        /// Calculate the modified feature value
        /// </summary>
        public virtual void SetModifiedValue(IAgent agent, IRobot robot){ }
        /// <summary>
        /// Obtains the feature modified or base value with the unit
        /// </summary>
        public virtual string FormattedValue
        {
            get { return string.Format(CultureInfo.CurrentCulture,"{0} {1}", IsModified ? ModifiedValue : Value, Unit); }
        }
        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(IFeature<T> other)
        {
            if (ReferenceEquals(null, other)) return false;
            return Equals(other.FeatureType, FeatureType);
        }
        /// <summary>
        /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </returns>
        /// <filterpriority>2</filterpriority>
        public override string ToString()
        {
            return Enum.GetName(typeof(FeaturesEnum), FeatureType);
        }
    }
}